﻿using System;
using System.Text.RegularExpressions;
using System.Web.Security;
using Domain;
using OS.Infrastructure.Domain.UnitOfWork;

namespace ShortUrl.Models
{
    public class AccountMembershipService : IMembershipService
    {
        private readonly IUnitOfWorkFactory unitOfWorkFactory;
        private readonly IAccountRepository accountRepository;
        readonly Regex regEx = new Regex(@"([-!#$%&'.*+/=?^`{}|~])+");

        public AccountMembershipService(IUnitOfWorkFactory unitOfWorkFactory, IAccountRepository accountRepository)
        {
            this.unitOfWorkFactory = unitOfWorkFactory;
            this.accountRepository = accountRepository;  
        }

        public int MinPasswordLength
        {
            get { return accountRepository.MinRequiredPasswordLength; }
        }

        public bool ValidateUser(string userName, string password)
        {
            using (IUnitOfWork unitOfWork = unitOfWorkFactory.Create())
            {
                var account = accountRepository.GetByName(userName);
                return account != null && account.Password == password;
            }
        }

        public MembershipCreateStatus CreateUser(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
            var status = new MembershipCreateStatus();
         
            using (IUnitOfWork unitOfWork = unitOfWorkFactory.Create())
            {
                if (regEx.IsMatch(userName))
                {
                    return MembershipCreateStatus.InvalidUserName;
                }
                if (regEx.IsMatch(password))
                {
                    return MembershipCreateStatus.InvalidPassword;
                }
                if (accountRepository.GetByName(userName) == null)
                {
                    var account = new Account();
                    account.NewAccount(userName, password);
                    accountRepository.Save(account);
                    status = unitOfWork.Commit() ? MembershipCreateStatus.Success : MembershipCreateStatus.UserRejected;
                }
                else return MembershipCreateStatus.DuplicateUserName;
            }
            return status;
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
            if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");
            if (regEx.IsMatch(newPassword))
            {
                return false;
            }
            bool status;
            using (IUnitOfWork unitOfWork = unitOfWorkFactory.Create())
            {
                Account currentUser = accountRepository.GetByName(userName);
                if (currentUser.ChangePassword(oldPassword, newPassword))
                    status = unitOfWork.Commit();
                else
                    return false;
            }
            return status;
        }
    }
}